package com.example.mysql_mybatis_demo.web;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.mysql_mybatis_demo.dao.AttrAttrgroupRelationDao;
import com.example.mysql_mybatis_demo.dao.AttrDao;
import com.example.mysql_mybatis_demo.dao.AttrGroupDao;
import com.example.mysql_mybatis_demo.entity.AttrAttrgroupRelationEntity;
import com.example.mysql_mybatis_demo.entity.AttrEntity;
import com.example.mysql_mybatis_demo.common.utils.R;
import com.example.mysql_mybatis_demo.entity.AttrGroupEntity;
import com.example.mysql_mybatis_demo.service.AttrGroupService;
import com.example.mysql_mybatis_demo.service.impl.AttrGroupServiceImpl;
import com.example.mysql_mybatis_demo.springsource.config.ApplicationContextAwareTest;
import com.example.mysql_mybatis_demo.vo.GroupingVo;
import com.example.mysql_mybatis_demo.vo.JoinSelectVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.w3c.dom.Attr;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

@RequestMapping("/mysql_mybatis_demo/index")
@RestController
public class IndexController {
    @Autowired
    private AttrDao attrDao;
    @Autowired
    private AttrGroupDao attrGroupDao;
    @Autowired
    private AttrAttrgroupRelationDao attrAttrgroupRelationDao;
    @Autowired
    private ApplicationContextAwareTest applicationContextAwareTest;
    @Autowired
    private AttrGroupService attrGroupService;

    @RequestMapping("/test")
    public R test() {
        AttrEntity attrEntity1 = new AttrEntity();
        attrEntity1.setAttrId(99L);
        attrEntity1.setAttrName("hh");
        attrDao.select_inter(99L);
        return R.ok();
    }

    @RequestMapping("/test2")
    public R test2() {
        List<AttrGroupEntity> attrGroupEntities = attrGroupDao.selectList(new QueryWrapper<AttrGroupEntity>().select("attr_group_name").apply("find_in_set({0}, descript)", "屏幕"));
        return R.ok().put("data", attrGroupEntities);
    }


    @RequestMapping("/test3")
    public void transTest(){
        attrGroupService.transTestImpl();
    }


    /**
     * 普通where查询。既可以使用querywapper也可以自己构造
     */
    @RequestMapping("/normalwhere")
    public R normalwhere() {
        R r = R.ok();

        attrDao.selectOne(new QueryWrapper<AttrEntity>().eq("d", 3));

        /**
         * 空值查询两种实现
         */
        List<AttrEntity> null_select = attrDao.selectList(new QueryWrapper<AttrEntity>().isNull("value_select"));
        List<AttrEntity> null_select_impl = attrDao.select_null_impl();
        r.put("null_select", null_select);
        r.put("null_select_impl", null_select_impl);

        /**
         * 非空查询两种实现
         */
        List<AttrEntity> not_null_select = attrDao.selectList(new QueryWrapper<AttrEntity>().isNotNull("value_select"));
        List<AttrEntity> not_null_select_impl = attrDao.select_not_null_impl();
//        r.put("not_null_select", not_null_select);
//        r.put("not_null_select_impl", not_null_select_impl);

        /**
         * between查询
         */
        List<AttrEntity> between_select = attrDao.selectList(new QueryWrapper<AttrEntity>().between("attr_id", 1, 5));
        List<AttrEntity> between_select_impl = attrDao.select_between_impl();
//        r.put("between_select", between_select);
//        r.put("between_select_impl", between_select_impl);

        /**
         * in查询
         */
        ArrayList<String> inList = new ArrayList<>();
        inList.add("品牌商");
        inList.add("机身内存");
        List<AttrEntity> in_select = attrDao.selectList(new QueryWrapper<AttrEntity>().in("attr_name", inList));
        List<AttrEntity> in_select_impl = attrDao.select_in_impl();
//        r.put("in_select", in_select);
//        r.put("in_select_impl", in_select_impl);


        return r;
    }

    /**
     * 正则查询，无 mybatis 实现
     */
    @RequestMapping("/regexpwhere")
    public R regexpwhere() {
        List<AttrEntity> regexp_select_impl = attrDao.select_regexp("小米");
        R r = R.ok().put("regexp_select_impl", regexp_select_impl);
        return r;
    }

    /**
     * Limit查询，无 Mybatis实现
     */
    @RequestMapping("/limitwhere")
    public R limitwhere() {
        List<AttrEntity> limit_select_impl = attrDao.select_limit_impl(2);
        R r = R.ok().put("limit_select_impl", limit_select_impl);
        return r;
    }

    /**
     * JOIN链接，无 Mybatis 实现
     */
    @RequestMapping("/join")
    public R join() {
        // 内连接不返回无法匹配的行
        // 外链接将无法匹配的行以 NUll返回。外链接直接在 LEFT JOIN 中间加 LEFT OUTER JOIN
        List<JoinSelectVo> join_select_impl = attrDao.select_join_impl();
        R r = R.ok().put("join_select_impl", join_select_impl);
        return r;
    }

    /**
     * 聚合函数.只有部分有 Mybatis 实现。因为 Mybatis只能返回Entity，而聚合函数大多数都是返回各种奇奇怪怪的值
     */
    @RequestMapping("/grouping")
    public R grouping() {
        R r = R.ok();

        // Mybatis自带count
        Integer countNum = attrDao.selectCount(new QueryWrapper<AttrEntity>().eq("attr_type", 1));
        // r.put("countNum", countNum);

        // MIN/AVG/MAX没有 mybatis 实现

        // GROUP BY 有Mybatis实现，但是不建议使用。因为没有办法做映射
        List<GroupingVo> grouping_select = attrDao.select_grouping();
        r.put("grouping_select", grouping_select);

        return r;
    }


    /**
     * 子查询.可以使用mysql直接实现，也可以用mybatis查询多次
     */
    @RequestMapping("/subselect")
    public R subselect() {
        R r = R.ok();

        // 特别是绕了很多圈的子查询问题，建议还是用MySQL直接实现，而非用mybatis
        // 子查询也可以用在 HAVING WHERE 中
        BigDecimal price = attrDao.selectOne(new QueryWrapper<AttrEntity>().eq("attr_id", 2)).getPrice();
        List<AttrEntity> sub_select = attrDao.selectList(new QueryWrapper<AttrEntity>().gt("price", price));
        List<AttrEntity> sub_select_impl = attrDao.select_sub_impl();
        r.put("sub_select", sub_select);
        r.put("sub_select_impl", sub_select_impl);
        return r;
    }


    /**
     * 视图操作。无 Mybatis 实现
     * 不过视图一旦创建后，和普通表没什么两样，所以使用起来和普通表完全相同的。
     * renren生成工具 也能识别到库中的视图。
     * 视图本身只存储SELECT语句，并不存储数据本身。每次到视图中查询数据时，其实视图先调用储存的SELECT语句构建自身。
     * 因此原表发生更改，视图一定能保持同步。
     * 视图更多的作用是用于查询，例如将原本在数据库中第二范式下的各个表链接起来，就不需要后端自己查两遍了
     * 注意，不建议修改视图的内容，虽然某些情况下视图可以将修改的内容更新到原表，但依然建议视图只用作查询
     */


    /**
     * function操作。无 Mybatis 实现
     * function一旦创建后，就和使用AVG/MIN等一样使用就行。不过一般不建议在MySQL中使用涉及到查询相关的function
     * function最好的用处是数据处理，而不是查询
     */
    @RequestMapping("/function")
    public R function() {
        R r = R.ok();
        BigDecimal function_select = attrDao.select_function_impl(7L);
        r.put("function_select", function_select);
        return r;
    }

    /**
     * Mybatis-plus的继承
     * mbp支持类继承。例如将 AttrAttrgroupRelationEntity 中的几个属性字段拆到父类 AttrAttrgroupRelationSuper中，
     * 完全不用改其他任何地方，系统正确运行。
     *
     * @return
     */
    @RequestMapping("/extendTest")
    public R extendTest() {
        AttrAttrgroupRelationEntity entity =
                attrAttrgroupRelationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("id", 1));
        // 此时entity是可以完整映射表中的所有字段的。同样直接使用 getxxx方法也可以获得任意属性字段的值(包括位于其父类中的属性字段)
        System.out.println(entity.getId());
        System.out.println(entity.getAttrId());
        System.out.println(entity.getAttrGroupId());
        System.out.println(entity.getAttrSort());
        return R.ok();
    }

}
